<?php
/**
 * Created by PhpStorm.
 * User: 35083
 * Date: 2019/7/16
 * Time: 16:37
 */

namespace app\task\controller;


class Systemtask
{
    /**
     * 系统级别任务，每日凌晨执行,最先执行 1
     */
    public function sysTask()
    {
        $this->sysClassListReward();//挑战 开奖
        $this->DoctorOrderJs();//挑战 开奖
    }

    /**
     * 应用级别  2
     */
    public function appTask()
    {
        //【系统任务】检查是否有循环任务需要执行，有的话就先执行系统任务
        $result = $this->addLoopTaskToQueue();
        if ($result) {//有
            return;
        }
        //【系统任务】检查定时推送消息，有就加入消息推送队列进行推送
        $result = $this->addTaskToQueue();
        if ($result) {//有
            return;
        }

        //【消息】检查是否有循环推送消息，这一个小时内 如果有就先加入推送队列进行消息推送
        $result = $this->addLoopTimeMsgToQueue();
        if ($result) {//有
            return;
        }

        /**
         * 获取上传思澜文件状态接口
         */
        $SleepReportPre_num=5;
        for ($i = 0; $i < $SleepReportPre_num; $i++) {
            $jsonString = \app\queue\Queue::pop(\app\queue\Queue::SleepReportPre);
            if (!empty($jsonString)) {
                $this->run($jsonString);
            }else
            {
                break;
            }
            if ($i = $SleepReportPre_num - 1) {
                return;
            }
        }
        //【消息】检查定时推送消息，有就加入消息推送队列进行推送
        $this->addTimeMsgToQueue();

    }

    /**
     * 用户级别任务 3
     */
    public function userTask()
    {

        //获取系统任务队列，执行系统任务 ，级别最高
        $system_num=5;
        for ($i = 0; $i < $system_num; $i++) {
            $jsonString = \app\queue\Queue::systemTaskPop();
            if (!empty($jsonString)) {
                $this->run($jsonString);
            }else
            {
                break;
            }
            if ($i = $system_num - 1) {
                return;
            }
        }

        //获取开奖后，给用户增加金额的队列 ,级别其次
        $money_num=5;
        for ($i = 0; $i < $money_num; $i++) {
            $jsonString = \app\queue\Queue::pop(\app\queue\Queue::Addusermoneytask);
            if (!empty($jsonString)) {
                $this->run($jsonString);
            }else{
                break;
            }
            if ($i = $money_num - 1) {
                return;
            }
        }
        //前端通知取报告
        $SleepReportPre10_num = 5;
        for ($i = 0; $i < $SleepReportPre10_num; $i++) {
            $jsonString = \app\queue\Queue::pop(\app\queue\Queue::SleepReportPre10);
            if (!empty($jsonString)) {
                $this->run($jsonString);
            } else {
                break;
            }
            if ($i = $SleepReportPre10_num - 1) {
                return;
            }
        }
        //获取睡眠报告相关队列 其二
        $SleepReport_num = 5;
        for ($i = 0; $i < $SleepReport_num; $i++) {
            $jsonString = \app\queue\Queue::pop(\app\queue\Queue::SleepReport);
            if (!empty($jsonString)) {
                $this->run($jsonString);
            } else {
                break;
            }
            if ($i = $SleepReport_num - 1) {
                return;
            }
        }
        //获取用户自定义队列 其三
        $user_num = 5;
        for ($i = 0; $i < $user_num; $i++) {
            $jsonString = \app\queue\Queue::userPop();
            if (!empty($jsonString)) {
                $this->run($jsonString);
            } else {
                break;
            }
            if ($i = $user_num - 1) {
                return;
            }
        }
    }

    /**
     * json字符串解码
     * @param $jsonString
     */
    private function jsonDecode($jsonString)
    {
        $taskInfo = json_decode($jsonString, true);
        switch (json_last_error()) {
            case JSON_ERROR_NONE:
                $result = array("err" => 0, "data" => $taskInfo);
                break;
            case JSON_ERROR_DEPTH:
                $result = array("err" => 1, "data" => ' - Maximum stack depth exceeded:' . $jsonString);
                break;
            case JSON_ERROR_STATE_MISMATCH:
                $result = array("err" => 1, "data" => ' - Underflow or the modes mismatch:' . $jsonString);
                break;
            case JSON_ERROR_CTRL_CHAR:
                $result = array("err" => 1, "data" => ' - Unexpected control character found:' . $jsonString);
                break;
            case JSON_ERROR_SYNTAX:
                $result = array("err" => 1, "data" => ' - Syntax error, malformed JSON:' . $jsonString);
                break;
            case JSON_ERROR_UTF8:
                $result = array("err" => 1, "data" => ' - Malformed UTF-8 characters, possibly incorrectly encoded:' . $jsonString);
                break;
            default:
                $result = array("err" => 1, "data" => ' - Unknown error:' . $jsonString);
                break;
        }
        return $result;
    }

    private function run($jsonString)
    {
        if (!empty($jsonString)) {
            $temp = $this->jsonDecode($jsonString);
            if ($temp['err'] > 0) {
                echo $temp['data'];
                return;
            }
            $taskInfo = $temp['data'];
            if (empty($taskInfo['path'])) {
                return;
            }
            $tempArray = $this->getInst($taskInfo['path']);
            if (empty($tempArray)) {
                return;
            }
            $modeString = $tempArray[0];
            $funString = $tempArray[1];

            $model = new $modeString();
            $result = $model->$funString($taskInfo['key'], $taskInfo['param']);
            //写入日志
            $this->taskLog($modeString . "#" . $funString, $taskInfo['param'], $taskInfo['key'], $result);
            //界面打印一个时间
            echo "yes:time:" . date("Y-m-d H:i:s") . ",key:" . $taskInfo['key'] . ",result:" . $result . "\r\n";
        } else {
            echo "no:time:" . date("Y-m-d H:i:s") . "\r\n";
        }

    }


    private function taskLog($taskname, $param, $key, $result)
    {
        if (is_array($param)) {
            $param = json_encode($param, true);
        }
        addTaskLog(array(
            'taskname' => $taskname,
            'key' => $key,
            'param' => $param,
            'result' => $result,
            'ctime' => date("Y-m-d H:i:s"),
        ));
    }

    private function getInst($path)
    {
        $temp = explode("#", $path);
        if (empty($temp)) {
            return array();
        }
        if (empty($temp[0])) {
            return array();
        }
        if (empty($temp[1])) {
            $temp[1] = "task";
        }
        return array($temp[0], $temp[1]);
    }

    /**
     *挑战结束分配奖励
     */
    private function sysClassListReward()
    {
        $currDate = getCurrDate();
        $model = new \app\admin\model\Classlist();
        $w = array(
            'reward_date' => $currDate['simple'],
            'reward_time' => array("elt", $currDate['hour'] . ":" . $currDate['minute']),
            'is_open_reward' => 0,//0未开奖 1已经开奖
            'is_auto_open_reward' => 0//0自动开奖 1手动开奖
        );
        $info = $model->getDataForWhere($w);
        if ($info) {
            classListReward($info['id']);
        }
        echo "time:" . date("Y-m-d H:i:s") . "\r\n";
    }

    /**
     * 医生订单数据结算
     */
    private function DoctorOrderJs()
    {
        $days = 1;//结算两天前的订单
        $num = 30;//每次结算订单的数量
        hospOrderJs($days, $num);
    }

    /**
     * 检查是否有循环执行任务 需要执行，有就加入任务执行队列里面
     * @return int
     */
    private function addLoopTaskToQueue()
    {
        $currDate = getCurrDate();
        $model = new  \app\admin\model\SystemTask();
        $push_time_val = $this->getCurPushLoopTimeVal();
        $sql = "select * from t_system_task where task_type='2' and is_delete='0' and time_val='{$push_time_val}' and stats='0' and last_run_date!='{$currDate['simple']}'";
        $list = $model->querySelectSQL($sql);
        if (empty($list)) {
            return 0;
        }
        $idsArray = array();
        foreach ($list as $key => $val) {
            $idsArray[] = $val['id'];
        }
        if (empty($idsArray)) {
            return 0;
        }

        $update = array('last_run_date' => $currDate['simple'], 'optime' => date("Y-m-d H:i:s"), 'stats' => 1);
        $w = array('id' => array('in', $idsArray));
        $res = $model->updateDataForWhere($update, $w);
        if ($res || $res === 0) {
            foreach ($list as $key => $val) {
                addTaskQueue($val);//添加app推送队列
            }
        }
        return 1;
    }

    /**
     * 检查每日循环消息，并加入队列
     * @return 0表示无数据，
     */
    private function addLoopTimeMsgToQueue()
    {
        $currDate = getCurrDate();
        $model = new  \app\admin\model\PushMsg();
        $push_time_val = $this->getCurPushLoopTimeVal();
        $sql = "select * from t_push_msg where push_time_type='2' and is_delete='0' and push_time_val='{$push_time_val}' and last_run_date!='{$currDate['simple']}'";
        $list = $model->querySelectSQL($sql);
        if (empty($list)) {
            return 0;
        }
        $idsArray = array();
        foreach ($list as $key => $val) {
            $idsArray[] = $val['id'];
        }
        if (empty($idsArray)) {
            return 0;
        }

        $update = array('last_run_date' => $currDate['simple'], 'is_avail_push' => 0);
        $w = array('id' => array('in', $idsArray));
        $res = $model->updateDataForWhere($update, $w);
        if ($res || $res === 0) {
            foreach ($idsArray as $key => $val) {
                addPushMsgQueue($val);//添加app推送队列
            }
        }
        return 1;
    }


    /**
     * 检查即将到的定时任务，并加入队列执行
     * @return 0表示无数据，
     */
    private function addTaskToQueue()
    {
        $currDate = getCurrDate();
        $model = new  \app\admin\model\SystemTask();
        $selectTime = $this->getCurPushTimeVal();
        $sql = "select * from t_system_task where  
        task_type='1' and is_delete='0' and 
        time_val >='{$selectTime['start']}' and  time_val <='{$selectTime['end']}' and stats='0' and  last_run_date =''";
        $list = $model->querySelectSQL($sql);
        if (empty($list)) {
            return 0;
        }
        $idsArray = array();
        foreach ($list as $key => $val) {
            $idsArray[] = $val['id'];
        }
        if (empty($idsArray)) {
            return 0;
        }

        $update = array('last_run_date' => $currDate['simple'], 'optime' => date("Y-m-d H:i:s"), 'stats' => 1);
        $w = array('id' => array('in', $idsArray));
        $res = $model->updateDataForWhere($update, $w);
        if ($res || $res === 0) {
            foreach ($list as $key => $val) {
                addTaskQueue($val);//添加app推送队列
            }
        }
        return 1;
    }

    /**
     * 检查即将到的定时任务，并加入队列
     * @return 0表示无数据，
     */
    private function addTimeMsgToQueue()
    {
        $currDate = getCurrDate();
        $model = new  \app\admin\model\PushMsg();
        $selectTime = $this->getCurPushTimeVal();
        $sql = "select * from t_push_msg where  is_avail_push ='1' and 
        push_time_type='1' and is_delete='0' and 
        push_time_val >='{$selectTime['start']}' and push_time_val <='{$selectTime['end']}'";
        $list = $model->querySelectSQL($sql);
        if (empty($list)) {
            return 0;
        }
        $idsArray = array();
        foreach ($list as $key => $val) {
            $idsArray[] = $val['id'];
        }
        if (empty($idsArray)) {
            return 0;
        }

        $update = array('last_run_date' => $currDate['simple'], 'is_avail_push' => 0);
        $w = array('id' => array('in', $idsArray));
        $res = $model->updateDataForWhere($update, $w);
        if ($res || $res === 0) {
            foreach ($idsArray as $key => $val) {
                addPushMsgQueue($val);//添加app推送队列
            }
        }
        return 1;
    }


    /**
     * 获取当前时间的左右N分钟时间范围
     */
    private function getCurPushTimeVal($during = 3)
    {
        $start = strtotime("-" . $during . "minutes");
        $end = strtotime("+" . $during . "minutes");
        return array('start' => formateDate($start), 'end' => formateDate($end));
    }

    /**
     * 获取本次应该查询的哪个时间值
     */
    private function getCurPushLoopTimeVal()
    {
        $currDate = getCurrDate();
        $string1 = $currDate['hour'];
        $string2 = "";
        if ($currDate['minute'] < 30) {
            $string2 = "00";
        } else {
            $string2 = "30";
        }
        return $string1 . ":" . $string2;
    }
}